<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="ROS1教程 3：ROS1的编译系统和ROS1的文件系统, python,machine learning,deep learning,html,css,c,c++,cpp,cmake,ros,linux,ubuntu">
    <meta name="description" content="本文是ROS1系列教程的第三篇文章，介绍了如何搭建ROS1的编译系统和ROS1的文件系统">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="referrer" content="no-referrer-when-downgrade">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>ROS1教程 3：ROS1的编译系统和ROS1的文件系统 | JackWang&#39;s Blog</title>
    <link rel="icon" type="image/png" href="/favicon.png">

    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">

    <script src="/libs/jquery/jquery-3.6.0.min.js"></script>

<meta name="generator" content="Hexo 5.4.2">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css">
<link rel="stylesheet" href="/css/prism-line-numbers.css" type="text/css"></head>



   <style>
    body{
       background-image: url(https://cdn.jsdelivr.net/gh/Tokisaki-Galaxy/res/site/medias/background.jpg);
       background-repeat:no-repeat;
       background-size: 100% 100%;
       background-attachment:fixed;
    }
</style>



<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <img src="/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">JackWang&#39;s Blog</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="" class="waves-effect waves-light">

      
      <i class="fas fa-book-reader" style="zoom: 0.6;"></i>
      
      <span>博客</span>
      <i class="fas fa-chevron-down" aria-hidden="true" style="zoom: 0.6;"></i>
    </a>
    <ul class="sub-nav menus_item_child ">
      
      <li>
        <a href="/tags">
          
          <i class="fas fa-tags" style="margin-top: -20px; zoom: 0.6;"></i>
          
	  <span>按标签归类文章</span>
        </a>
      </li>
      
      <li>
        <a href="/categories">
          
          <i class="fas fa-bookmark" style="margin-top: -20px; zoom: 0.6;"></i>
          
	  <span>按目录归类文章</span>
        </a>
      </li>
      
      <li>
        <a href="/archives">
          
          <i class="fas fa-archive" style="margin-top: -20px; zoom: 0.6;"></i>
          
	  <span>按日期分类文章</span>
        </a>
      </li>
      
    </ul>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>



<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">JackWang&#39;s Blog</div>
        <div class="logo-desc">
            
            JackWang的个人博客
            
        </div>
    </div>

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="javascript:;">
			
				<i class="fa-fw fas fa-book-reader"></i>
			
			博客
			<span class="m-icon"><i class="fas fa-chevron-right"></i></span>
		</a>
            <ul  style="background:  ;" >
              
                <li>

                  <a href="/tags " style="margin-left:75px">
				  
				   <i class="fa fas fa-tags" style="position: absolute;left:50px" ></i>
			      
                              <span>按标签归类文章</    span>

                  </a>
                </li>
              
                <li>

                  <a href="/categories " style="margin-left:75px">
				  
				   <i class="fa fas fa-bookmark" style="position: absolute;left:50px" ></i>
			      
                              <span>按目录归类文章</    span>

                  </a>
                </li>
              
                <li>

                  <a href="/archives " style="margin-left:75px">
				  
				   <i class="fa fas fa-archive" style="position: absolute;left:50px" ></i>
			      
                              <span>按日期分类文章</    span>

                  </a>
                </li>
              
            </ul>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        
    </ul>
</div>


        </div>

        
    </nav>

</header>

    
<script src="/libs/cryptojs/crypto-js.min.js"></script>
<script>
    (function() {
        let pwd = '';
        if (pwd && pwd.length > 0) {
            if (pwd !== CryptoJS.SHA256(prompt('抱歉，这篇文章并不想让所有人都看到，请输入授权密码观看')).toString(CryptoJS.enc.Hex)) {
                alert('密码错误，将返回主页！');
                location.href = '/';
            }
        }
    })();
</script>




<div class="bg-cover pd-header post-cover" style="background-image: url('https://jack-1307599355.cos.ap-shanghai.myqcloud.com/%E5%B1%8F%E5%B9%95%E5%BD%95%E5%88%B62022-12-24%20%E4%B8%8B%E5%8D%888.22.34.gif')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">ROS1教程 3：ROS1的编译系统和ROS1的文件系统</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/ROS/">
                                <span class="chip bg-color">ROS</span>
                            </a>
                        
                            <a href="/tags/catkin-make/">
                                <span class="chip bg-color">catkin_make</span>
                            </a>
                        
                            <a href="/tags/ROS1/">
                                <span class="chip bg-color">ROS1</span>
                            </a>
                        
                            <a href="/tags/ROS1%E6%95%99%E7%A8%8B/">
                                <span class="chip bg-color">ROS1教程</span>
                            </a>
                        
                            <a href="/tags/ROS1%E7%BC%96%E8%AF%91%E7%B3%BB%E7%BB%9F/">
                                <span class="chip bg-color">ROS1编译系统</span>
                            </a>
                        
                            <a href="/tags/ROS1%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/">
                                <span class="chip bg-color">ROS1文件系统</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/categories/ROS1%E6%95%99%E7%A8%8B/" class="post-category">
                                ROS1教程
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2022-12-24
                </div>
                

                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-check fa-fw"></i>更新日期:&nbsp;&nbsp;
                    2023-11-01
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    4.3k
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-clock fa-fw"></i>阅读时长:&nbsp;&nbsp;
                    18 分
                </div>
                

                
                    <div id="busuanzi_container_page_pv" class="info-break-policy">
                        <i class="far fa-eye fa-fw"></i>阅读次数:&nbsp;&nbsp;
                        <span id="busuanzi_value_page_pv"></span>
                    </div>
				
            </div>
        </div>
        <hr class="clearfix">

        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/%E5%B1%8F%E5%B9%95%E5%BD%95%E5%88%B62022-12-24%20%E4%B8%8B%E5%8D%888.22.34.gif" alt="ROS1编译系统"></p>
<h1 id="ROS1教程-3：ROS1的编译系统和ROS1的文件系统"><a href="#ROS1教程-3：ROS1的编译系统和ROS1的文件系统" class="headerlink" title="ROS1教程 3：ROS1的编译系统和ROS1的文件系统"></a>ROS1教程 3：ROS1的编译系统和ROS1的文件系统</h1><p>其实，我们上一节在测试的<code>ROS1</code>开发环境的时候，就已经涉及到了<code>ROS1</code>的编译系统和文件系统。但是我们始终没有正是介绍他们，所以在下一章我们正是开始编写<code>ROS1</code>代码前，我们先介绍<code>ROS1</code>的编译系统和<code>ROS1</code>的文件系统。</p>
<h2 id="1-ROS1编译系统：Catkin"><a href="#1-ROS1编译系统：Catkin" class="headerlink" title="1. ROS1编译系统：Catkin"></a>1. ROS1编译系统：Catkin</h2><p>我们前面在<code>ROS1</code>的介绍中说过，<code>ROS1</code>是<code>Willow Garage</code>这家公司创造的，而<code>catkin</code>这个词的本意是柔荑，即柳树的花的名字。所以其实，<code>catkin</code>就是回应了<code>Willow Garage</code>公司</p>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221224180613231.png" alt="Catkin, 柔荑" style="zoom:50%;"></p>
<h3 id="1-1-什么是编译系统？"><a href="#1-1-什么是编译系统？" class="headerlink" title="1.1 什么是编译系统？"></a>1.1 什么是编译系统？</h3><p><strong><code>编译系统</code>负责编译源代码，生成最终的目标</strong>。目标可以是<strong>库</strong>、<strong>可执行程序</strong>、<strong>（自动生成的）脚本</strong>、<strong>（自动导出的）接口</strong>（例如 C++ 头文件）或任何其他非静态代码的形式。</p>
<p>在软件开发中广泛使用的流行编译系统包括：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://www.gnu.org/software/make/">GNU Make</a></li>
<li><a target="_blank" rel="noopener" href="http://www.gnu.org/software/autoconf/">GNU Autotools</a></li>
<li><a target="_blank" rel="noopener" href="http://www.cmake.org/">CMake</a></li>
<li><a target="_blank" rel="noopener" href="http://ant.apache.org/">Apache Ant</a>（主要用于 Java）</li>
</ul>
<p>此外，还有Google的<a target="_blank" rel="noopener" href="https://bazel.build/">Bazel</a>、微软的<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Visual_Build">Visual Build</a>等等。</p>
<p>几乎所有集成开发环境，例如<code>Qt Creator</code>、<code>Microsoft Visual Studio</code>和<code>Eclipse</code>，都为它们支持的相应语言创造了自己的编译系统，例如<code>QMake</code>和<code>Visual Build</code>。这些 IDE 中的编译系统通常都是给其他的编译系统进行了包装，例如：<code>Autotools</code>、<code>CMake</code>。即<code>QMake</code>和<code>Visual Build</code>都是<code>Autotools</code>和<code>Cmake</code>的前端。</p>
<p>要构建目标，编译系统需要一套工具，即工具链，包括：<code>C++</code>编译器、链接器等等。而除了这些工具以外，编译系统还需要这些工具的其他信息，例如工具的位置、源代码的位置、代码依赖项、外部依赖项、这些依赖项位于何处、要编译哪些目标、生成的编译目标的位置等信息，以及它们应该安装的位置……</p>
<p>这些信息通常保存在一个文件之后，而后在调用编译系统编译的时候，编译系统会读取的文件中的内容，而后按照文件中的规矩进行编译。这个文件称为配置文件。例如<code>CMake</code>中，它的配置文件通常命名为<code>CMakeLists.txt</code>，而<code>GNU Make</code>，它的配置文件通常命名为<code>Makefile</code>。而在IDE中，则通常把配置文件中的信息存储为工作区/项目的元信息，例如<code>Visual C++</code>项目文件的一部分。</p>
<p>类似的，<code>ROS1</code>使用自定义构建系统<code>catkin</code>，它是基于<code>CMake</code>的构建系统，以管理包之间的依赖关系。</p>
<h3 id="1-2-为什么-ROS1-有自定义编译系统？"><a href="#1-2-为什么-ROS1-有自定义编译系统？" class="headerlink" title="1.2 为什么 ROS1 有自定义编译系统？"></a>1.2 为什么 ROS1 有自定义编译系统？</h3><p>对于单个软件项目的开发，<code>Autotools</code>、<code>CMake</code>等现有编译系统往往就够用了。然而，这些工具虽然可以胜任大型、复杂、高度异构（包含多种语言写成的代码）的项目的编译，但是往往可能需要复杂的配置，因为特定目标可能具有大量的依赖项。</p>
<blockquote>
<p>例如项目可能需要分别编译<code>C/C++</code>代码和<code>rust</code>代码，然后运行的时候又需要先运行<code>Python</code>脚本启动客户端去链接<code>Java</code>代码写的服务器……</p>
</blockquote>
<p>如此复杂的项目中具有大量特定的链接方式、自定义的构建规则和运行规则，但是<code>Autotools</code>和<code>CMake</code>是面向通用项目的。因此需要在<code>Autotools</code>和<code>CMake</code>的配置文件中需要进行大量的设置才能够编译复杂的项目，因此没有软件开发背景的人也往往难以实现。</p>
<p>而<code>ROS1</code>恰巧正如上面所说，<code>ROS1</code>是一个非常大的松散联合包集合。不同的包之间可能是用不同的语言写成的，各自都有不同的依赖、开发工具工具和代码组织约定。因此，某些包中目标的编译过程可能与另一个的编译方式完全不同。例如A公司的机器人的机械臂的代码使用<code>CMake</code>去编译代码，而B公司的地盘的代码使用<code>Autotools</code>编译。</p>
<p>因此，为了屏蔽包与包之间的编译的差异，<code>ROS1</code>提供了一个更加高层的编译系统，即<code>catkin</code>编译系统。具体来说，<code>catkin</code>对<code>CMake</code>进行了扩展，为其添加了很多的扩展配置，例如专门用于<code>ROS1</code>的<code>CMake</code>函数等等。所以换句话说，<code>catkin</code>都旨在通过使用工具和约定来简化<code>ROS1</code>的编译过程，从而使得编译和运行<code>ROS1</code>代码变得更加容易。没有它，有效地共享<code>ROS1</code>的代码将更加困难。</p>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21hb19odWlfZmVp,size_16,color_FFFFFF,t_70.png" alt="catkin编译系统的层次" style="zoom:43%;"></p>
<h3 id="1-3-rosbuild与catkin-make"><a href="#1-3-rosbuild与catkin-make" class="headerlink" title="1.3 rosbuild与catkin_make"></a>1.3 rosbuild与catkin_make</h3><p>事实上，<code>ROS1</code>最初的编译系统是<code>rosbuild</code>，后来才换成了<code>catkin</code></p>
<p>因为在<code>ROS1</code>的早期版本中，<code>rosbuild</code>作为<code>ROS1</code>的编译系统运行良好。但随着<code>ROS1</code>代码库的快速增长以及多年的运用已经暴露出<code>rosbuild</code>设计时的一些缺点，因此<code>catkin</code>试图弥补这些缺点。</p>
<p>举一个例子，<code>rosbuild</code>的最大问题之一是它不能轻松的移植到所有操作系统，尤其是<code>Windows</code>。这是因为<code>rosbuild</code>混合使用<code>Bash</code>脚本、<code>GNU Make</code>和 <code>CMake</code>来构建代码。在<code>rosbuild</code>中，当我们调用编译系统时，我们必须调用 <code>rosbuild</code> 提供的自定义脚本，例如<code>rosmake</code>。<code>rosmake</code>是一个调用<code>make</code>的 <code>Bash</code> 脚本，它本身调用 <code>CMake</code>，<code>CMake</code> 生成另一个 <code>makefile</code>，最后再次调用<code>make</code>。属实是太不优雅了。而<code>catkin</code>更优雅，只需调用 <code>CMake</code> 即可完成编译。</p>
<p><code>Catkin</code> 中自定义非常多的 <code>CMake</code> 宏以及一些<code>Python</code>代码实现的。由于<code>CMake</code>和<code>Python</code>都是多平台通用的，因此<code>catkin</code>可以轻松移植到任何同时支持<code>Python</code>和<code>CMake</code>的系统。事实上，<code>catkin</code> 项目以与其他 <code>CMake</code> 项目无缝使用——构建 <code>catkin</code> 项目时，它们还会生成导出信息，允许在别的<code>CMake</code>项目中使用<code>CMake</code>的函数 <code>find_package()</code>函数找到它们。</p>
<p>除了复杂的编译流程外，还有：次优的设计决策、黑客攻击和不必要的复杂性等等问题，因此这些问题促使<code>ROS1</code>替换掉<code>rosbuild</code>。</p>
<h3 id="1-4-Catkin编译系统和文件系统的配合"><a href="#1-4-Catkin编译系统和文件系统的配合" class="headerlink" title="1.4 Catkin编译系统和文件系统的配合"></a>1.4 Catkin编译系统和文件系统的配合</h3><p>一个复杂的项目需要很好的文件结构规划，而<code>ROS1</code>中<code>catkin</code>编译系统能够很好的和<code>ROS1</code>的文件系统配合。</p>
<h2 id="2-ROS1的文件系统"><a href="#2-ROS1的文件系统" class="headerlink" title="2. ROS1的文件系统"></a>2. ROS1的文件系统</h2><p>所谓文件系统，指的是文件在硬盘上的存储方式。因此<code>ROS1</code>的文件系统指的就是硬盘上<code>ROS1</code>源代码的组织形式，其结构大致可以如下图所示：</p>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F.jpg" alt="ROS1的文件系统"></p>
<h3 id="2-1-概述"><a href="#2-1-概述" class="headerlink" title="2.1 概述"></a>2.1 概述</h3><p><code>ROS1</code>文件系统中各个文件的作用的解释如下：</p>
<pre class="line-numbers language-bash"><code class="language-bash">WorkSpace --- 自定义的工作空间

    <span class="token operator">|</span>--- build:编译空间，用于存放CMake和catkin的缓存信息、配置信息和其他中间文件。

    <span class="token operator">|</span>--- devel:开发空间，用于存放编译后生成的目标文件，包括头文件、动态<span class="token operator">&amp;</span>静态链接库、可执行文件等。

    <span class="token operator">|</span>--- src: 源码

        <span class="token operator">|</span>-- package：功能包<span class="token punctuation">(</span>ROS1基本单元<span class="token punctuation">)</span>包含多个节点、库与配置文件，包名所有字母小写，只能由字母、数字与下划线组成

            <span class="token operator">|</span>-- CMakeLists.txt 配置编译规则，比如源文件、依赖项、目标文件

            <span class="token operator">|</span>-- package.xml 包信息，比如:包名、版本、作者、依赖项<span class="token punctuation">..</span>.<span class="token punctuation">(</span>以前版本是 manifest.xml<span class="token punctuation">)</span>

            <span class="token operator">|</span>-- scripts 存储python文件

            <span class="token operator">|</span>-- src 存储C++源文件

            <span class="token operator">|</span>-- include 头文件

            <span class="token operator">|</span>-- msg 消息通信格式文件

            <span class="token operator">|</span>-- srv 服务通信格式文件

            <span class="token operator">|</span>-- action 动作格式文件

            <span class="token operator">|</span>-- launch 可一次性运行多个节点 

            <span class="token operator">|</span>-- config 配置信息

        <span class="token operator">|</span>-- CMakeLists.txt: 编译的基本配置
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><code>ROS1</code> 文件系统中各个目录下的内容后面教程会逐一进行介绍，目前我们主要介绍：<code>package.xml</code>与<code>CMakeLists.txt</code>这两个配置文件。</p>
<h3 id="2-2-Package-xml"><a href="#2-2-Package-xml" class="headerlink" title="2.2 Package.xml"></a>2.2 Package.xml</h3><p><code>package.xml</code>是<code>catkin</code>编译系统的一部分，该文件定义了一个<code>catkin</code>软件包的属性，例如<strong>软件包名称</strong>，<strong>版本号</strong>，<strong>作者</strong>，<strong>维护者</strong>以及对其他<code>catkin</code>软件包的依赖性。请注意，该概念类似于旧版 <code>rosbuild</code> 构建系统中使用的<code>manifest.xml</code>文件。</p>
<p>对一个标准的<code>package.xml</code>的注释如下</p>
<pre class="line-numbers language-xml"><code class="language-xml"><span class="token prolog">&lt;?xml version="1.0"?></span>
<span class="token comment" spellcheck="true">&lt;!-- 格式: 以前是 1，推荐使用格式 2 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>package</span> <span class="token attr-name">format</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token comment" spellcheck="true">&lt;!-- 包名 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">></span></span>example<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">></span></span>
  <span class="token comment" spellcheck="true">&lt;!-- 版本 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.0.1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
  <span class="token comment" spellcheck="true">&lt;!-- 描述信息 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>description</span><span class="token punctuation">></span></span>Example of package.xml<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>description</span><span class="token punctuation">></span></span>

  <span class="token comment" spellcheck="true">&lt;!-- One maintainer tag required, multiple allowed, one person per tag --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Example:  --></span>
  <span class="token comment" spellcheck="true">&lt;!-- &lt;maintainer email="jane.doe@example.com">Jane Doe&lt;/maintainer> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- 维护人员 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>maintainer</span> <span class="token attr-name">email</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jack3shihong@gmail.com<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>jackwang<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>maintainer</span><span class="token punctuation">></span></span>


  <span class="token comment" spellcheck="true">&lt;!-- One license tag required, multiple allowed, one license per tag --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Commonly used license strings: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --></span>
  <span class="token comment" spellcheck="true">&lt;!-- 许可证信息，ROS1核心组件默认 BSD --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>license</span><span class="token punctuation">></span></span>BSD<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>license</span><span class="token punctuation">></span></span>


  <span class="token comment" spellcheck="true">&lt;!-- Url tags are optional, but multiple are allowed, one per tag --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Optional attribute type can be: website, bugtracker, or repository --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Example: --></span>
  <span class="token comment" spellcheck="true">&lt;!-- &lt;url type="website">http://wiki.ROS1.org/demo01_hello_vscode&lt;/url> --></span>


  <span class="token comment" spellcheck="true">&lt;!-- Author tags are optional, multiple are allowed, one per tag --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Authors do not have to be maintainers, but could be --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Example: --></span>
  <span class="token comment" spellcheck="true">&lt;!-- &lt;author email="jane.doe@example.com">Jane Doe&lt;/author> --></span>


  <span class="token comment" spellcheck="true">&lt;!-- The *depend tags are used to specify dependencies --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Dependencies can be catkin packages or system dependencies --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Examples: --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use depend as a shortcut for packages that are both build and exec dependencies --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;depend>roscpp&lt;/depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!--   Note that this is equivalent to the following: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;build_depend>roscpp&lt;/build_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;exec_depend>roscpp&lt;/exec_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use build_depend for packages you need at compile time: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;build_depend>message_generation&lt;/build_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use build_export_depend for packages you need in order to build against this package: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;build_export_depend>message_generation&lt;/build_export_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use buildtool_depend for build tool packages: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;buildtool_depend>catkin&lt;/buildtool_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use exec_depend for packages you need at runtime: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;exec_depend>message_runtime&lt;/exec_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use test_depend for packages you need only for testing: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;test_depend>gtest&lt;/test_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- Use doc_depend for packages you need only for building documentation: --></span>
  <span class="token comment" spellcheck="true">&lt;!--   &lt;doc_depend>doxygen&lt;/doc_depend> --></span>
  <span class="token comment" spellcheck="true">&lt;!-- 依赖的构建工具，这是必须的 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>buildtool_depend</span><span class="token punctuation">></span></span>catkin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>buildtool_depend</span><span class="token punctuation">></span></span>

  <span class="token comment" spellcheck="true">&lt;!-- 指定构建此软件包所需的软件包 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_depend</span><span class="token punctuation">></span></span>roscpp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_depend</span><span class="token punctuation">></span></span>rospy<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_depend</span><span class="token punctuation">></span></span>std_msgs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_depend</span><span class="token punctuation">></span></span>

  <span class="token comment" spellcheck="true">&lt;!-- 指定根据这个包构建库所需要的包 --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_export_depend</span><span class="token punctuation">></span></span>roscpp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_export_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_export_depend</span><span class="token punctuation">></span></span>rospy<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_export_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build_export_depend</span><span class="token punctuation">></span></span>std_msgs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build_export_depend</span><span class="token punctuation">></span></span>

  <span class="token comment" spellcheck="true">&lt;!-- 运行该程序包中的代码所需的程序包 --></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>exec_depend</span><span class="token punctuation">></span></span>roscpp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>exec_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>exec_depend</span><span class="token punctuation">></span></span>rospy<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>exec_depend</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>exec_depend</span><span class="token punctuation">></span></span>std_msgs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>exec_depend</span><span class="token punctuation">></span></span>


  <span class="token comment" spellcheck="true">&lt;!-- The export tag contains other, unspecified, tags --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>export</span><span class="token punctuation">></span></span>
    <span class="token comment" spellcheck="true">&lt;!-- Other tools can request additional information be placed here --></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>export</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>package</span><span class="token punctuation">></span></span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h3 id="2-3-CMakeLists-txt"><a href="#2-3-CMakeLists-txt" class="headerlink" title="2.3 CMakeLists.txt"></a>2.3 CMakeLists.txt</h3><p><code>CMakeLists.txt</code>是<code>CMake</code>构建系统的输入，用于构建软件包。任何兼容<code>CMake</code>的软件包都包含一个或多个<code>CMakeLists.txt</code>文件，这些文件描述了如何构建代码以及将代码安装到何处。</p>
<p>我们前面说到，<code>catkin</code>是给<code>CMake</code>做了扩展，添加了<code>ROS1</code>专用的函数，因此<code>ROS1</code>文件系统中需要有一个<code>CMakeLists.txt</code>，而<code>catkin</code>编译的时候会调用<code>CMake</code>去读取<code>CMakeLists.txt</code>中的数据</p>
<p>下面是一个包中的<code>CMakeLists.txt</code>的内容：</p>
<pre class="line-numbers language-cmake"><code class="language-cmake">make_minimum_required(VERSION 3.0.2) #所需 cmake 版本
project(example) #包名称，会被 ${PROJECT_NAME} 的方式调用

## Compile as C++11, supported in ROS1 Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
#设置构建所需要的软件包
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
)

## System dependencies are found with CMake's conventions
#默认添加系统依赖
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ROS1.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# 启动 python 模块支持
# catkin_python_setup()

################################################
## Declare ROS1 messages, services and actions ##
## 声明 ROS1 消息、服务、动作... ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# 生成消息、服务时的依赖包
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS1 dynamic reconfigure parameters ##
## 声明 ROS1 动态参数配置 ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
## catkin 特定配置##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
# 运行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo01_hello_vscode
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
# 添加头文件路径，当前程序包的头文件路径位于其他文件路径之前
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# 声明 C++ 库
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/demo01_hello_vscode.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# 添加库的 cmake 目标依赖
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# 声明 C++ 可执行文件
add_executable(Test src/test.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
#重命名c++可执行文件
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
#添加可执行文件的 cmake 目标依赖
add_dependencies(Test ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
#指定库、可执行文件的链接库
target_link_libraries(Test
  ${catkin_LIBRARIES}
)

#############
## Install ##
## 安装 ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ROS1.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
#设置用于安装的可执行脚本
catkin_install_python(PROGRAMS
  scripts/test.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

## Mark executables for installation
## See http://docs.ROS1.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ROS1.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_demo01_hello_vscode.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h3 id="2-4-ROS1文件系统常用命令"><a href="#2-4-ROS1文件系统常用命令" class="headerlink" title="2.4 ROS1文件系统常用命令"></a>2.4 ROS1文件系统常用命令</h3><p>上面介绍了<code>ROS1</code>文件系统，下面介绍<code>ROS1</code>文件系统中常用的命令。事实上，<code>ROS1</code>其实是有一整套命令的，每个命令下其实都是有很多选项的，所有其实是有非常非常多的功能的，我们这里只是针对常用的功能来介绍某个命令中的某个选项。</p>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221227104855150.png" alt="image-20221227104855150"></p>
<h4 id="A-新增包"><a href="#A-新增包" class="headerlink" title="A. 新增包"></a>A. 新增包</h4><p>包可以自己创建然后自己写</p>
<pre class="line-numbers language-bash"><code class="language-bash">catkin_create_pkg 自定义包名 依赖包
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>这样的话，包就会创建在当前所在的<code>工作目录(Current Working Directory)</code>下</p>
<p>此外，也可以从APT中下载，因为我们前面添加过软件源了</p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token function">sudo</span> apt <span class="token function">install</span> ROS1-版本号-包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><code>Tab</code>补全就会显示当前版本可以安装的软件包，例如：</p>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225112851912.png" alt="APT直接安装ROS1包"></p>
<p>而通过<code>APT</code>安装的软件包，最后都会被安装到环境变量<code>ROS_PACKAGE_PATH</code>所表示的路径中。这个路径如果没有修改的话，默认是<code>/opt/ROS1/noetic/share</code></p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token keyword">echo</span> <span class="token variable">$ROS_PACKAGE_PATH</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225122503637.png" alt="image-20221225122503637"></p>
<h4 id="B-删除包"><a href="#B-删除包" class="headerlink" title="B. 删除包"></a>B. 删除包</h4><p>对于使用<code>catkin_create_pkg</code>创建的包，直接删除就好了，即：</p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token function">cd</span> 工作目录
<span class="token function">rm</span> -r src/要删除的包名
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
<p>而对于<code>APT</code>安装的包，使用<code>APT</code>即可删除</p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token function">sudo</span> apt purge ROS1-版本号-包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<h4 id="C-查询包"><a href="#C-查询包" class="headerlink" title="C. 查询包"></a>C. 查询包</h4><h5 id="rospack-list"><a href="#rospack-list" class="headerlink" title="rospack list"></a>rospack list</h5><p><code>rospack list</code>可以列出所有功能包</p>
<pre class="line-numbers language-bash"><code class="language-bash">rospack list
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225123547298.png" alt="rospack列出所有的包"></p>
<h5 id="rospack-find"><a href="#rospack-find" class="headerlink" title="rospack find"></a>rospack find</h5><p><code>rospack find</code>可以查找某个功能包是否存在，如果存在返回安装路径</p>
<pre class="line-numbers language-bash"><code class="language-bash">rospack <span class="token function">find</span> 功能包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>当然<code>rospack</code>命令下还有很多选项，后面用到了我们再慢慢介绍</p>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash">rospack <span class="token function">find</span> tf2
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225123909375.png" alt="rospack find"></p>
<h5 id="roscd"><a href="#roscd" class="headerlink" title="roscd"></a>roscd</h5><p><code>roscd</code>可以进入某个功能包</p>
<pre class="line-numbers language-bash"><code class="language-bash">roscd 功能包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token function">pwd</span>
roscd rospy
<span class="token function">pwd</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225124226914.png" alt="roscd rospy"></p>
<h5 id="rosls"><a href="#rosls" class="headerlink" title="rosls"></a>rosls</h5><p><code>rosl</code>用于列出某个包下的文件</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosls 包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosls roscpp
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225124602959.png" alt="rosls roscpp"></p>
<h5 id="apt-search"><a href="#apt-search" class="headerlink" title="apt search"></a>apt search</h5><p>我们前面说到，可以用<code>APT</code>直接从网上下载<code>ROS1</code>功能包，所以我们可以用<code>apt search</code>去搜索功能包</p>
<pre class="line-numbers language-bash"><code class="language-bash">apt search ROS1-版本号-包名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash"><span class="token function">sudo</span> apt search ROS1-noetic-ROS1-py
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225124950933.png" alt="apt search"></p>
<h4 id="D-修改包"><a href="#D-修改包" class="headerlink" title="D. 修改包"></a>D. 修改包</h4><p><code>rosed</code>可以直接修改包中的文件</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosed 功能包名 要修改的文件名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>需要注意的是，<code>rosed</code>会调用<code>EDITOR</code>环境变量中表明的编辑器来打开文件</p>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosed rospy rospy.cmake
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225130305431.png" alt="rosed"></p>
<h4 id="E-运行"><a href="#E-运行" class="headerlink" title="E. 运行"></a>E. 运行</h4><h5 id="roscore"><a href="#roscore" class="headerlink" title="roscore"></a>roscore</h5><p><code>roscore</code> 是 <code>ROS1</code> 的系统先决条件节点和程序的集合， 必须运行 <code>roscore</code> 才能使 <code>ROS1</code> 节点进行通信。</p>
<p><code>roscore</code> 将启动:</p>
<ul>
<li><code>ROS1 master</code></li>
<li><code>ROS1</code>参数服务器</li>
<li><code>rosout</code> 日志节点</li>
</ul>
<p>用法:</p>
<pre class="line-numbers language-bash"><code class="language-bash">roscore
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>或(指定端口号)</p>
<pre class="line-numbers language-bash"><code class="language-bash">roscore -p xxxx
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<h5 id="rosrun"><a href="#rosrun" class="headerlink" title="rosrun"></a>rosrun</h5><p><code>rosrun</code>可以运行指定的ROS1节点</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosrun 功能包名 可执行文件名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p>例如：</p>
<pre class="line-numbers language-bash"><code class="language-bash">rosrun turtlesim turtlesim_node
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>
<p><img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/image-20221225132910112.png" alt="rosrun"></p>
<h5 id="roslaunch"><a href="#roslaunch" class="headerlink" title="roslaunch"></a>roslaunch</h5><p><code>roslaunch</code>用于直接执行某个包下的<code>launch</code>文件</p>
<pre class="line-numbers language-bash"><code class="language-bash">roslaunch 功能包名 launch文件名
<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">Jack Wang</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://jackwang0107.github.io/2022/12/24/ros-jiao-cheng-3-ros-de-bian-yi-xi-tong-he-ros-de-wen-jian-xi-tong/">https://jackwang0107.github.io/2022/12/24/ros-jiao-cheng-3-ros-de-bian-yi-xi-tong-he-ros-de-wen-jian-xi-tong/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">Jack Wang</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/ROS/">
                                    <span class="chip bg-color">ROS</span>
                                </a>
                            
                                <a href="/tags/catkin-make/">
                                    <span class="chip bg-color">catkin_make</span>
                                </a>
                            
                                <a href="/tags/ROS1/">
                                    <span class="chip bg-color">ROS1</span>
                                </a>
                            
                                <a href="/tags/ROS1%E6%95%99%E7%A8%8B/">
                                    <span class="chip bg-color">ROS1教程</span>
                                </a>
                            
                                <a href="/tags/ROS1%E7%BC%96%E8%AF%91%E7%B3%BB%E7%BB%9F/">
                                    <span class="chip bg-color">ROS1编译系统</span>
                                </a>
                            
                                <a href="/tags/ROS1%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/">
                                    <span class="chip bg-color">ROS1文件系统</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/medias/reward/alipay.png" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/medias/reward/wechat.jpg" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/2022/12/25/ros-jiao-cheng-4-hello-world-li-cheng/">
                    <div class="card-image">
                        
                        <img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/new/%E5%B1%8F%E5%B9%95%E5%BD%95%E5%88%B62022-12-25%20%E4%B8%8A%E5%8D%883.27.36.gif" class="responsive-img" alt="ROS1教程 4：Hello World例程">
                        
                        <span class="card-title">ROS1教程 4：Hello World例程</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            本文是ROS1系列教程的第四篇文章，介绍了如何实现ROS1的Hello World例程
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2022-12-25
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/ROS1%E6%95%99%E7%A8%8B/" class="post-category">
                                    ROS1教程
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/ROS/">
                        <span class="chip bg-color">ROS</span>
                    </a>
                    
                    <a href="/tags/catkin-make/">
                        <span class="chip bg-color">catkin_make</span>
                    </a>
                    
                    <a href="/tags/ROS1/">
                        <span class="chip bg-color">ROS1</span>
                    </a>
                    
                    <a href="/tags/ROS1%E6%95%99%E7%A8%8B/">
                        <span class="chip bg-color">ROS1教程</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/2022/12/23/ros-jiao-cheng-2-ros-kai-fa-huan-jing-da-jian/">
                    <div class="card-image">
                        
                        <img src="https://jack-1307599355.cos.ap-shanghai.myqcloud.com/%E5%B1%8F%E5%B9%95%E5%BD%95%E5%88%B62022-12-24%20%E4%B8%8B%E5%8D%881.26.48.gif" class="responsive-img" alt="ROS1教程 2：ROS1开发环境搭建">
                        
                        <span class="card-title">ROS1教程 2：ROS1开发环境搭建</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            本文是ROS1系列教程的第二篇文章，介绍了如何搭建ROS1开发环境
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2022-12-23
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/ROS1%E6%95%99%E7%A8%8B/" class="post-category">
                                    ROS1教程
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/ROS/">
                        <span class="chip bg-color">ROS</span>
                    </a>
                    
                    <a href="/tags/ROS1/">
                        <span class="chip bg-color">ROS1</span>
                    </a>
                    
                    <a href="/tags/ROS1%E6%95%99%E7%A8%8B/">
                        <span class="chip bg-color">ROS1教程</span>
                    </a>
                    
                    <a href="/tags/ROS1%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/">
                        <span class="chip bg-color">ROS1开发环境搭建</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>


<script>
    $('#articleContent').on('copy', function (e) {
        // IE8 or earlier browser is 'undefined'
        if (typeof window.getSelection === 'undefined') return;

        var selection = window.getSelection();
        // if the selection is short let's not annoy our users.
        if (('' + selection).length < Number.parseInt('120')) {
            return;
        }

        // create a div outside of the visible area and fill it with the selected text.
        var bodyElement = document.getElementsByTagName('body')[0];
        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        bodyElement.appendChild(newdiv);
        newdiv.appendChild(selection.getRangeAt(0).cloneContents());

        // we need a <pre> tag workaround.
        // otherwise the text inside "pre" loses all the line breaks!
        if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'PRE' || selection.getRangeAt(0).commonAncestorContainer.nodeName === 'CODE') {
            newdiv.innerHTML = "<pre>" + newdiv.innerHTML + "</pre>";
        }

        var url = document.location.href;
        newdiv.innerHTML += '<br />'
            + '来源: JackWang&#39;s Blog<br />'
            + '文章作者: Jack Wang<br />'
            + '文章链接: <a href="' + url + '">' + url + '</a><br />'
            + '本文章著作权归作者所有，任何形式的转载都请注明出处。';

        selection.selectAllChildren(newdiv);
        window.setTimeout(function () {bodyElement.removeChild(newdiv);}, 200);
    });
</script>


<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('2'),
            headingSelector: 'h1, h2, h3, h4, h5, h6'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h1, h2, h3, h4, h5, h6').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    

    <div class="container row center-align"
         style="margin-bottom: 15px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2021-2023</span>
            
            <a href="/about" target="_blank">Jack Wang</a>
            <!-- |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a> -->
            <!-- |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a> -->
            <br>
            
                &nbsp;<i class="fas fa-chart-area"></i>&nbsp;站点总字数:&nbsp;<span
                        class="white-color">603.8k</span>
            
            
            
                
            
            
                <span id="busuanzi_container_site_pv">
                &nbsp;|&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;
                    <span id="busuanzi_value_site_pv" class="white-color"></span>
            </span>
            
            
                <span id="busuanzi_container_site_uv">
                &nbsp;|&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;
                    <span id="busuanzi_value_site_uv" class="white-color"></span>
            </span>
            
            <br>

            <!-- 运行天数提醒. -->
            
                <span id="sitetime"> Loading ...</span>
                <script>
                    var calcSiteTime = function () {
                        var seconds = 1000;
                        var minutes = seconds * 60;
                        var hours = minutes * 60;
                        var days = hours * 24;
                        var years = days * 365;
                        var today = new Date();
                        var startYear = "2021";
                        var startMonth = "11";
                        var startDate = "12";
                        var startHour = "0";
                        var startMinute = "0";
                        var startSecond = "0";
                        var todayYear = today.getFullYear();
                        var todayMonth = today.getMonth() + 1;
                        var todayDate = today.getDate();
                        var todayHour = today.getHours();
                        var todayMinute = today.getMinutes();
                        var todaySecond = today.getSeconds();
                        var t1 = Date.UTC(startYear, startMonth, startDate, startHour, startMinute, startSecond);
                        var t2 = Date.UTC(todayYear, todayMonth, todayDate, todayHour, todayMinute, todaySecond);
                        var diff = t2 - t1;
                        var diffYears = Math.floor(diff / years);
                        var diffDays = Math.floor((diff / days) - diffYears * 365);

                        // 区分是否有年份.
                        var language = 'zh-CN';
                        if (startYear === String(todayYear)) {
                            document.getElementById("year").innerHTML = todayYear;
                            var daysTip = 'This site has been running for ' + diffDays + ' days';
                            if (language === 'zh-CN') {
                                daysTip = '本站已运行 ' + diffDays + ' 天';
                            } else if (language === 'zh-HK') {
                                daysTip = '本站已運行 ' + diffDays + ' 天';
                            }
                            document.getElementById("sitetime").innerHTML = daysTip;
                        } else {
                            document.getElementById("year").innerHTML = startYear + " - " + todayYear;
                            var yearsAndDaysTip = 'This site has been running for ' + diffYears + ' years and '
                                + diffDays + ' days';
                            if (language === 'zh-CN') {
                                yearsAndDaysTip = '本站已运行 ' + diffYears + ' 年 ' + diffDays + ' 天';
                            } else if (language === 'zh-HK') {
                                yearsAndDaysTip = '本站已運行 ' + diffYears + ' 年 ' + diffDays + ' 天';
                            }
                            document.getElementById("sitetime").innerHTML = yearsAndDaysTip;
                        }
                    }

                    calcSiteTime();
                </script>
            
            <br>
            
                <span id="icp"><img src="/medias/icp.png"
                                    style="vertical-align: text-bottom;"/>
                <a href="https://beian.miit.gov.cn" target="_blank">陕ICP备2021014294号-1</a>
            </span>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://github.com/jackwang0108" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="mailto:2232123545@qq.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2232123545" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 2232123545" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    

    
        
        <script type="text/javascript">
            // 只在桌面版网页启用特效
            var windowWidth = $(window).width();
            if (windowWidth > 768) {
                document.write('<script type="text/javascript" src="/libs/others/sakura.js"><\/script>');
            }
        </script>
    

    <!-- 雪花特效 -->
    

    <!-- 鼠标星星特效 -->
    

     
        <script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
        <script src="/libs/others/TencentCaptcha.js"></script>
        <button id="TencentCaptcha" data-appid="xxxxxxxxxx" data-cbfn="callback" type="button" hidden></button>
    

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    <!--腾讯兔小巢-->
    
    

    

    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    

</body>

</html>
